<!doctype html>
<html class="default no-js">
<head>
	<meta charset="utf-8">
	<meta http-equiv="X-UA-Compatible" content="IE=edge">
	<title>vuex-persist</title>
	<meta name="description" content="">
	<meta name="viewport" content="width=device-width, initial-scale=1">
	<link rel="stylesheet" href="assets/css/main.css">
</head>
<body>
<header>
	<div class="tsd-page-toolbar">
		<div class="container">
			<div class="table-wrap">
				<div class="table-cell" id="tsd-search" data-index="assets/js/search.js" data-base=".">
					<div class="field">
						<label for="tsd-search-field" class="tsd-widget search no-caption">Search</label>
						<input id="tsd-search-field" type="text" />
					</div>
					<ul class="results">
						<li class="state loading">Preparing search index...</li>
						<li class="state failure">The search index is not available</li>
					</ul>
					<a href="index.html" class="title">vuex-persist</a>
				</div>
				<div class="table-cell" id="tsd-widgets">
					<div id="tsd-filter">
						<a href="#" class="tsd-widget options no-caption" data-toggle="options">Options</a>
						<div class="tsd-filter-group">
							<div class="tsd-select" id="tsd-filter-visibility">
								<span class="tsd-select-label">All</span>
								<ul class="tsd-select-list">
									<li data-value="public">Public</li>
									<li data-value="protected">Public/Protected</li>
									<li data-value="private" class="selected">All</li>
								</ul>
							</div>
							<input type="checkbox" id="tsd-filter-inherited" checked />
							<label class="tsd-widget" for="tsd-filter-inherited">Inherited</label>
							<input type="checkbox" id="tsd-filter-externals" checked />
							<label class="tsd-widget" for="tsd-filter-externals">Externals</label>
							<input type="checkbox" id="tsd-filter-only-exported" />
							<label class="tsd-widget" for="tsd-filter-only-exported">Only exported</label>
						</div>
					</div>
					<a href="#" class="tsd-widget menu no-caption" data-toggle="menu">Menu</a>
				</div>
			</div>
		</div>
	</div>
	<div class="tsd-page-title">
		<div class="container">
			<ul class="tsd-breadcrumb">
				<li>
					<a href="globals.html">Globals</a>
				</li>
			</ul>
			<h1> vuex-persist</h1>
		</div>
	</div>
</header>
<div class="container container-main">
	<div class="row">
		<div class="col-8 col-content">
			<div class="tsd-panel tsd-typography">
				<a href="#vuex-persist" id="vuex-persist" style="color: inherit; text-decoration: none;">
					<h1>vuex-persist</h1>
				</a>
				<p>A Typescript-ready <a href="https://vuex.vuejs.org/">Vuex</a> plugin that enables
					you to save the state of your app to a persisted storage like
				Cookies or localStorage.</p>
				<p><a href="https://paypal.me/championswimmer"><img src="https://img.shields.io/badge/Donate-Paypal-2244dd.svg" alt="Paypal Donate"></a></p>
				<p><strong>Info :</strong>
					<a href="http://github.com/championswimmer/vuex-persist"><img src="https://img.shields.io/github/stars/championswimmer/vuex-persist.svg?style=social&label=%20vuex-persist" alt="GitHub stars"></a>
					<a href="http://npmjs.com/vuex-persist"><img src="https://img.shields.io/npm/v/vuex-persist.svg?colorB=dd1100" alt="npm"></a>
					<a href="http://npmjs.com/vuex-persist"><img src="https://img.shields.io/npm/dw/vuex-persist.svg?colorB=fc4f4f" alt="npm"></a>
				<a href=""><img src="https://img.shields.io/github/license/championswimmer/vuex-persist.svg" alt="license"></a></p>
				<p><strong>Status :</strong>
					<a href="https://travis-ci.org/championswimmer/vuex-persist"><img src="https://travis-ci.org/championswimmer/vuex-persist.svg?branch=master" alt="Build Status"></a>
					<a href="https://codebeat.co/projects/github-com-championswimmer-vuex-persist-master"><img src="https://codebeat.co/badges/dc97dea1-1e70-45d5-b3f1-fec2a6c3e4b0" alt="codebeat badge"></a>
					<a href="https://www.codacy.com/app/championswimmer/vuex-persist?utm_source=github.com&amp;utm_medium=referral&amp;utm_content=championswimmer/vuex-persist&amp;utm_campaign=Badge_Grade"><img src="https://api.codacy.com/project/badge/Grade/0fdc0921591d4ab98b0c0c173ef22649" alt="Codacy Badge"></a>
					<a href="https://codeclimate.com/github/championswimmer/vuex-persist"><img src="https://codeclimate.com/github/championswimmer/vuex-persist/badges/gpa.svg" alt="Code Climate"></a>
				<a href="https://codecov.io/gh/championswimmer/vuex-persist"><img src="https://codecov.io/gh/championswimmer/vuex-persist/branch/master/graph/badge.svg" alt="codecov"></a></p>
				<p><strong>Sizes :</strong>
					<a href="https://bundlephobia.com/result?p=vuex-persist"><img src="https://img.shields.io/bundlephobia/minzip/vuex-persist.svg?label=npm:size:gzip" alt="npm:size:gzip"></a>
					<a href="https://unpkg.com/vuex-persist"><img src="https://img.badgesize.io/https://unpkg.com/vuex-persist?compression=gzip&label=umd:min:gzip" alt="umd:min:gzip"></a>
				<a href="https://cdn.jsdelivr.net/npm/vuex-persist"><img src="https://img.badgesize.io/https://cdn.jsdelivr.net/npm/vuex-persist?compression=brotli&label=umd:min:brotli" alt="umd:min:brotli"></a></p>
				<a href="#table-of-contents" id="table-of-contents" style="color: inherit; text-decoration: none;">
					<h4>Table of Contents</h4>
				</a>
				<ul>
					<li><a href="#vuex-persist">vuex-persist</a><pre><code><span class="hljs-bullet">- </span>[<span class="hljs-string">Table of Contents</span>](<span class="hljs-link">#table-of-contents</span>)</code></pre><ul>
							<li><a href="#features">Features</a></li>
							<li><a href="#compatibility">Compatibility</a></li>
							<li><a href="#installation">Installation</a><ul>
									<li><a href="#vue-cli-build-setup-using-webpack-or-some-bundler">Vue CLI Build Setup (using Webpack or some bundler)</a></li>
									<li><a href="#transpile-for-target-es5">Transpile for <code>target: es5</code></a></li>
									<li><a href="#directly-in-browser">Directly in Browser</a></li>
									<li><a href="#tips-for-nuxt">Tips for NUXT</a></li>
								</ul>
							</li>
							<li><a href="#usage">Usage</a><ul>
									<li><a href="#steps">Steps</a></li>
									<li><a href="#constructor-parameters">Constructor Parameters -</a></li>
									<li><a href="#usage-notes">Usage Notes</a><ul>
											<li><a href="#reducer">Reducer</a></li>
											<li><a href="#circular-states">Circular States</a></li>
										</ul>
									</li>
								</ul>
							</li>
							<li><a href="#examples">Examples</a><ul>
									<li><a href="#simple">Simple</a></li>
									<li><a href="#detailed">Detailed</a></li>
									<li><a href="#support-strict-mode">Support Strict Mode</a></li>
									<li><a href="#note-on-localforage-and-async-stores">Note on LocalForage and async stores</a></li>
									<li><a href="#how-to-know-when-async-store-has-been-replaced">How to know when async store has been replaced</a></li>
								</ul>
							</li>
							<li><a href="#unit-testing">Unit Testing</a><ul>
									<li><a href="#jest">Jest</a></li>
								</ul>
							</li>
						</ul>
					</li>
				</ul>
				<p><small><i><a href='http://ecotrust-canada.github.io/markdown-toc/'>Table of contents generated with markdown-toc</a></i></small></p>
				<a href="#features" id="features" style="color: inherit; text-decoration: none;">
					<h2>Features</h2>
				</a>
				<ul>
					<li>📦 NEW in v1.5<ul>
							<li>distributed as esm and cjs both (via module field of package.json)</li>
							<li>better tree shaking as a result of esm</li>
						</ul>
					</li>
					<li>🎗 NEW IN V1.0.0<ul>
							<li>Support localForage and other Promise based stores</li>
							<li>Fix late restore of state for localStorage</li>
						</ul>
					</li>
					<li>Automatically save store on mutation.</li>
					<li>Choose which mutations trigger store save, and which don&#39;t, using <code>filter</code> function</li>
					<li>Works perfectly with modules in store</li>
					<li>Ability to save partial store, using a <code>reducer</code> function</li>
					<li>Automatically restores store when app loads</li>
					<li>You can create mulitple VuexPersistence instances if you want to -<ul>
							<li>Save some parts of the store to localStorage, some to sessionStorage</li>
							<li>Trigger saving to localStorage on data download, saving to cookies on authentication result</li>
						</ul>
					</li>
				</ul>
				<a href="#compatibility" id="compatibility" style="color: inherit; text-decoration: none;">
					<h2>Compatibility</h2>
				</a>
				<ul>
					<li><a href="http://vuejs.org">VueJS</a> - v2.0 and above</li>
					<li><a href="http://vuex.vuejs.org">Vuex</a> - v2.1 and above</li>
				</ul>
				<a href="#installation" id="installation" style="color: inherit; text-decoration: none;">
					<h2>Installation</h2>
				</a>
				<a href="#vue-cli-build-setup-using-webpack-or-some-bundler" id="vue-cli-build-setup-using-webpack-or-some-bundler" style="color: inherit; text-decoration: none;">
					<h3>Vue CLI Build Setup (using Webpack or some bundler)</h3>
				</a>
				<pre><code class="language-shell">npm install --save vuex-persist</code></pre>
				<p>or</p>
				<pre><code class="language-shell">yarn add vuex-persist</code></pre>
				<a href="#transpile-for-codetarget-es5code" id="transpile-for-codetarget-es5code" style="color: inherit; text-decoration: none;">
					<h3>Transpile for <code>target: es5</code></h3>
				</a>
				<p>This module is distributed in 3 formats</p>
				<ul>
					<li>umd build <code>/dist/umd/index.js</code> in <strong>es5</strong> format</li>
					<li>commonjs build <code>/dist/cjs/index.js</code> in <strong>es2015</strong> format</li>
					<li>esm build <code>/dist/esm/index.js</code> in <strong>es2015</strong> format</li>
				</ul>
				<p>When using with Webpack (or Vue CLI 3), the esm file gets used by default.
					If your project has a <code>es6</code> or <code>es2015</code> target, you&#39;re good, but if
					for backwards compatibility, you are compiling your project to <code>es5</code> then
				this module also needs to be transpiled.</p>
				<p>To enable transpilation of this module</p>
				<pre><code class="language-js"><span class="hljs-comment">// in your vue.config.js</span>
<span class="hljs-built_in">module</span>.exports = {
  <span class="hljs-comment">/* ... other config ... */</span>
  <span class="hljs-attr">transpileDependencies</span>: [<span class="hljs-string">'vuex-persist'</span>]
}</code></pre>
				<a href="#directly-in-browser" id="directly-in-browser" style="color: inherit; text-decoration: none;">
					<h3>Directly in Browser</h3>
				</a>
				<pre><code class="language-html"><span class="hljs-comment">&lt;!-- We need lodash.merge so get lodash first --&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.10/lodash.min.js"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://cdn.jsdelivr.net/npm/vuex-persist"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span></code></pre>
				<a href="#tips-for-nuxt" id="tips-for-nuxt" style="color: inherit; text-decoration: none;">
					<h3>Tips for NUXT</h3>
				</a>
				<p>This is a plugin that works <a href="https://nuxtjs.org/guide/plugins/#client-side-only">only on the client side</a>.
				So we&#39;ll register it as a ssr-free plugin.</p>
				<pre><code class="language-js"><span class="hljs-comment">// Inside - nuxt.config.js</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> {
  <span class="hljs-attr">plugins</span>: [
    { <span class="hljs-attr">src</span>: <span class="hljs-string">'~/plugins/vuex-persist'</span>, <span class="hljs-attr">ssr</span>: <span class="hljs-literal">false</span> }
  ]
}</code></pre>
				<pre><code class="language-js"><span class="hljs-comment">// ~/plugins/vuex-persist.js</span>
<span class="hljs-keyword">import</span> VuexPersistence <span class="hljs-keyword">from</span> <span class="hljs-string">'vuex-persist'</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> ({ store }) =&gt; {
  <span class="hljs-keyword">new</span> VuexPersistence({
  <span class="hljs-comment">/* your options */</span>
  }).plugin(store);
}</code></pre>
				<a href="#usage" id="usage" style="color: inherit; text-decoration: none;">
					<h2>Usage</h2>
				</a>
				<a href="#steps" id="steps" style="color: inherit; text-decoration: none;">
					<h3>Steps</h3>
				</a>
				<p>Import it</p>
				<pre><code class="language-js"><span class="hljs-keyword">import</span> VuexPersistence <span class="hljs-keyword">from</span> <span class="hljs-string">'vuex-persist'</span></code></pre>
				<blockquote>
					<p>NOTE: In browsers, you can directly use <code>window.VuexPersistence</code></p>
				</blockquote>
				<p>Create an object</p>
				<pre><code class="language-ts"><span class="hljs-keyword">const</span> vuexLocal = <span class="hljs-keyword">new</span> VuexPersistence({
  storage: <span class="hljs-built_in">window</span>.localStorage
})

<span class="hljs-comment">// or in Typescript</span>

<span class="hljs-keyword">const</span> vuexLocal = <span class="hljs-keyword">new</span> VuexPersistence&lt;RootState&gt;({
  storage: <span class="hljs-built_in">window</span>.localStorage
})
</code></pre>
				<p>Use it as Vue plugin. (in typescript)</p>
				<pre><code class="language-typescript"><span class="hljs-keyword">const</span> store = <span class="hljs-keyword">new</span> Vuex.Store&lt;State&gt;({
  state: { ... },
  mutations: { ... },
  actions: { ... },
  plugins: [vuexLocal.plugin]
})</code></pre>
				<p>(or in Javascript)</p>
				<pre><code class="language-js"><span class="hljs-keyword">const</span> store = {
  <span class="hljs-attr">state</span>: { ... },
  <span class="hljs-attr">mutations</span>: { ... },
  <span class="hljs-attr">actions</span>: { ... },
  <span class="hljs-attr">plugins</span>: [vuexLocal.plugin]
}</code></pre>
				<a href="#constructor-parameters--" id="constructor-parameters--" style="color: inherit; text-decoration: none;">
					<h3>Constructor Parameters -</h3>
				</a>
				<p>When creating the VuexPersistence object, we pass an <code>options</code> object
					of type <code>PersistOptions</code>.
				Here are the properties, and what they mean -</p>
				<table>
					<thead>
						<tr>
							<th>Property</th>
							<th>Type</th>
							<th>Description</th>
						</tr>
					</thead>
					<tbody><tr>
							<td>key</td>
							<td>string</td>
							<td>The key to store the state in the storage <br><em><strong>Default: &#39;vuex&#39;</strong></em></td>
						</tr>
						<tr>
							<td>storage</td>
							<td>Storage (Web API)</td>
							<td>localStorage, sessionStorage, localforage or your custom Storage object. <br>Must implement getItem, setItem, clear etc. <br> <em><strong>Default: window.localStorage</strong></em></td>
						</tr>
						<tr>
							<td>saveState</td>
							<td>function<br> (key, state[, storage])</td>
							<td>If not using storage, this custom function handles <br>saving state to persistence</td>
						</tr>
						<tr>
							<td>restoreState</td>
							<td>function<br> (key[, storage]) =&gt; state</td>
							<td>If not using storage, this custom function handles <br>retrieving state from storage</td>
						</tr>
						<tr>
							<td>reducer</td>
							<td>function<br> (state) =&gt; object</td>
							<td>State reducer. reduces state to only those values you want to save. <br>By default, saves entire state</td>
						</tr>
						<tr>
							<td>filter</td>
							<td>function<br> (mutation) =&gt; boolean</td>
							<td>Mutation filter. Look at <code>mutation.type</code> and return true <br>for only those ones which you want a persistence write to be triggered for. <br> Default returns true for all mutations</td>
						</tr>
						<tr>
							<td>modules</td>
							<td>string[]</td>
							<td>List of modules you want to persist. (Do not write your own reducer if you want to use this)</td>
						</tr>
						<tr>
							<td>asyncStorage</td>
							<td>boolean</td>
							<td>Denotes if the store uses Promises (like localforage) or not (you must set this to true when suing something like localforage) <br><em><strong>Default: false</strong></em></td>
						</tr>
						<tr>
							<td>supportCircular</td>
							<td>boolean</td>
							<td>Denotes if the state has any circular references to itself (state.x === state) <br><em><strong>Default: false</strong></em></td>
						</tr>
				</tbody></table>
				<a href="#usage-notes" id="usage-notes" style="color: inherit; text-decoration: none;">
					<h3>Usage Notes</h3>
				</a>
				<a href="#reducer" id="reducer" style="color: inherit; text-decoration: none;">
					<h4>Reducer</h4>
				</a>
				<p>Your reducer should not change the shape of the state.</p>
				<pre><code class="language-javascript"><span class="hljs-keyword">const</span> persist = <span class="hljs-keyword">new</span> VuexPersistence({
  <span class="hljs-attr">reducer</span>: <span class="hljs-function">(<span class="hljs-params">state</span>) =&gt;</span> state.products,
  ...
})</code></pre>
				<p>Above code is <strong>wrong</strong>
				You intend to do this instead</p>
				<pre><code class="language-js"><span class="hljs-keyword">const</span> persist = <span class="hljs-keyword">new</span> VuexPersistence({
  <span class="hljs-attr">reducer</span>: <span class="hljs-function">(<span class="hljs-params">state</span>) =&gt;</span> ({<span class="hljs-attr">products</span>: state.products}),
  ...
})</code></pre>
				<a href="#circular-states" id="circular-states" style="color: inherit; text-decoration: none;">
					<h4>Circular States</h4>
				</a>
				<p>If you have circular structures in your state</p>
				<pre><code class="language-js"><span class="hljs-keyword">let</span> x = { <span class="hljs-attr">a</span>: <span class="hljs-number">10</span> }
x.x = x
x.x === x.x.x <span class="hljs-comment">// true</span>
x.x.x.a === x.x.x.x.a <span class="hljs-comment">//true</span></code></pre>
				<p><code>JSON.parse()</code> and <code>JSON.stringify()</code> will not work.
				You&#39;ll need to install <code>flatted</code></p>
				<pre><code>npm <span class="hljs-keyword">install</span> flatted</code></pre><p>And when constructing the store, add <code>supportCircular</code> flag</p>
				<pre><code class="language-js"><span class="hljs-keyword">new</span> VuexPersistence({
  <span class="hljs-attr">supportCircular</span>: <span class="hljs-literal">true</span>,
  ...
})</code></pre>
				<a href="#examples" id="examples" style="color: inherit; text-decoration: none;">
					<h2>Examples</h2>
				</a>
				<a href="#simple" id="simple" style="color: inherit; text-decoration: none;">
					<h3>Simple</h3>
				</a>
				<p>Quick example -</p>
				<pre><code class="language-typescript"><span class="hljs-keyword">import</span> Vue <span class="hljs-keyword">from</span> <span class="hljs-string">'vue'</span>
<span class="hljs-keyword">import</span> Vuex <span class="hljs-keyword">from</span> <span class="hljs-string">'vuex'</span>
<span class="hljs-keyword">import</span> VuexPersistence <span class="hljs-keyword">from</span> <span class="hljs-string">'vuex-persist'</span>

Vue.use(Vuex)

<span class="hljs-keyword">const</span> store = <span class="hljs-keyword">new</span> Vuex.Store&lt;State&gt;({
  state: {
    user: { name: <span class="hljs-string">'Arnav'</span> },
    navigation: { path: <span class="hljs-string">'/home'</span> }
  },
  plugins: [<span class="hljs-keyword">new</span> VuexPersistence().plugin]
})

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> store</code></pre>
				<a href="#detailed" id="detailed" style="color: inherit; text-decoration: none;">
					<h3>Detailed</h3>
				</a>
				<p>Here is an example store that has 2 modules, <code>user</code> and <code>navigation</code>
					We are going to save user details into a Cookie <em>(using js-cookie)</em>
					And, we will save the navigation state into <em>localStorage</em> whenever
					a new item is added to nav items.
					So you can use multiple VuexPersistence instances to store different
				parts of your Vuex store into different storage providers.</p>
				<p><strong>Warning:</strong> when working with modules these should be registered in
					the Vuex constructor. When using <code>store.registerModule</code> you risk the
					(restored) persisted state being overwritten with the default state
				defined in the module itself.</p>
				<pre><code class="language-typescript"><span class="hljs-keyword">import</span> Vue <span class="hljs-keyword">from</span> <span class="hljs-string">'vue'</span>
<span class="hljs-keyword">import</span> Vuex, { Payload, Store } <span class="hljs-keyword">from</span> <span class="hljs-string">'vuex'</span>
<span class="hljs-keyword">import</span> VuexPersistence <span class="hljs-keyword">from</span> <span class="hljs-string">'vuex-persist'</span>
<span class="hljs-keyword">import</span> Cookies <span class="hljs-keyword">from</span> <span class="hljs-string">'js-cookie'</span>
<span class="hljs-keyword">import</span> { <span class="hljs-keyword">module</span> as userModule, UserState } from './user'
import navModule, { NavigationState } <span class="hljs-keyword">from</span> <span class="hljs-string">'./navigation'</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">interface</span> State {
  user: UserState
  navigation: NavigationState
}

Vue.use(Vuex)

<span class="hljs-keyword">const</span> vuexCookie = <span class="hljs-keyword">new</span> VuexPersistence&lt;State, Payload&gt;({
  restoreState: <span class="hljs-function">(<span class="hljs-params">key, storage</span>) =&gt;</span> Cookies.getJSON(key),
  saveState: <span class="hljs-function">(<span class="hljs-params">key, state, storage</span>) =&gt;</span>
    Cookies.set(key, state, {
      expires: <span class="hljs-number">3</span>
    }),
  modules: [<span class="hljs-string">'user'</span>], <span class="hljs-comment">//only save user module</span>
  filter: <span class="hljs-function">(<span class="hljs-params">mutation</span>) =&gt;</span> mutation.type == <span class="hljs-string">'logIn'</span> || mutation.type == <span class="hljs-string">'logOut'</span>
})
<span class="hljs-keyword">const</span> vuexLocal = <span class="hljs-keyword">new</span> VuexPersistence&lt;State, Payload&gt;({
  storage: <span class="hljs-built_in">window</span>.localStorage,
  reducer: <span class="hljs-function">(<span class="hljs-params">state</span>) =&gt;</span> ({ navigation: state.navigation }), <span class="hljs-comment">//only save navigation module</span>
  filter: <span class="hljs-function">(<span class="hljs-params">mutation</span>) =&gt;</span> mutation.type == <span class="hljs-string">'addNavItem'</span>
})

<span class="hljs-keyword">const</span> store = <span class="hljs-keyword">new</span> Vuex.Store&lt;State&gt;({
  modules: {
    user: userModule,
    navigation: navModule
  },
  plugins: [vuexCookie.plugin, vuexLocal.plugin]
})

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> store</code></pre>
				<a href="#support-strict-mode" id="support-strict-mode" style="color: inherit; text-decoration: none;">
					<h3>Support Strict Mode</h3>
				</a>
				<p>This now supports <a href="https://vuex.vuejs.org/en/strict.html">Vuex strict mode</a>
					(Keep in mind, <strong>NOT</strong> to use strict mode in production)
				In strict mode, we cannot use <code>store.replaceState</code> so instead we use a mutation</p>
				<p>You&#39;ll need to keep in mind to add the <strong><code>RESTORE_MUTATION</code></strong> to your mutations
				See example below</p>
				<p>To configure with strict mode support -</p>
				<pre><code class="language-typescript"><span class="hljs-keyword">import</span> Vue <span class="hljs-keyword">from</span> <span class="hljs-string">'vue'</span>
<span class="hljs-keyword">import</span> Vuex, { Payload, Store } <span class="hljs-keyword">from</span> <span class="hljs-string">'vuex'</span>
<span class="hljs-keyword">import</span> VuexPersistence <span class="hljs-keyword">from</span> <span class="hljs-string">'vuex-persist'</span>

<span class="hljs-keyword">const</span> vuexPersist = <span class="hljs-keyword">new</span> VuexPersistence&lt;<span class="hljs-built_in">any</span>, <span class="hljs-built_in">any</span>&gt;({
  strictMode: <span class="hljs-literal">true</span>, <span class="hljs-comment">// This **MUST** be set to true</span>
  storage: localStorage,
  reducer: <span class="hljs-function">(<span class="hljs-params">state</span>) =&gt;</span> ({ dog: state.dog }),
  filter: <span class="hljs-function">(<span class="hljs-params">mutation</span>) =&gt;</span> mutation.type === <span class="hljs-string">'dogBark'</span>
})

<span class="hljs-keyword">const</span> store = <span class="hljs-keyword">new</span> Vuex.Store&lt;State&gt;({
  strict: <span class="hljs-literal">true</span>, <span class="hljs-comment">// This makes the Vuex store strict</span>
  state: {
    user: {
      name: <span class="hljs-string">'Arnav'</span>
    },
    foo: {
      bar: <span class="hljs-string">'baz'</span>
    }
  },
  mutations: {
    RESTORE_MUTATION: vuexPersist.RESTORE_MUTATION <span class="hljs-comment">// this mutation **MUST** be named "RESTORE_MUTATION"</span>
  },
  plugins: [vuexPersist.plugin]
})</code></pre>
				<p>Some of the most popular ways to persist your store would be -</p>
				<ul>
					<li><strong><a href="https://npmjs.com/js-cookie">js-cookie</a></strong> to use browser Cookies</li>
					<li><strong>window.localStorage</strong> (remains, across PC reboots, untill you clear browser data)</li>
					<li><strong>window.sessionStorage</strong> (vanishes when you close browser tab)</li>
					<li><strong><a href="http://npmjs.com/localforage">localForage</a></strong> Uses IndexedDB from the browser</li>
				</ul>
				<a href="#note-on-localforage-and-async-stores" id="note-on-localforage-and-async-stores" style="color: inherit; text-decoration: none;">
					<h3>Note on LocalForage and async stores</h3>
				</a>
				<p>There is Window.Storage API as defined by HTML5 DOM specs, which implements the following -</p>
				<pre><code class="language-typescript"><span class="hljs-keyword">interface</span> Storage {
  readonly length: <span class="hljs-built_in">number</span>
  clear(): <span class="hljs-built_in">void</span>
  getItem(key: <span class="hljs-built_in">string</span>): <span class="hljs-built_in">string</span> | <span class="hljs-literal">null</span>
  key(index: <span class="hljs-built_in">number</span>): <span class="hljs-built_in">string</span> | <span class="hljs-literal">null</span>
  removeItem(key: <span class="hljs-built_in">string</span>): <span class="hljs-built_in">void</span>
  setItem(key: <span class="hljs-built_in">string</span>, data: <span class="hljs-built_in">string</span>): <span class="hljs-built_in">void</span>
  [key: <span class="hljs-built_in">string</span>]: <span class="hljs-built_in">any</span>
  [index: <span class="hljs-built_in">number</span>]: <span class="hljs-built_in">string</span>
}</code></pre>
				<p>As you can see it is an entirely synchronous storage. Also note that it
				saves only string values. Thus objects are stringified and stored.</p>
				<p>Now note the representative interface of Local Forage -</p>
				<pre><code class="language-typescript"><span class="hljs-keyword">export</span> <span class="hljs-keyword">interface</span> LocalForage {
  getItem&lt;T&gt;(key: <span class="hljs-built_in">string</span>): <span class="hljs-built_in">Promise</span>&lt;T&gt;
  setItem&lt;T&gt;(key: <span class="hljs-built_in">string</span>, data: T): <span class="hljs-built_in">Promise</span>&lt;T&gt;
  removeItem(key: <span class="hljs-built_in">string</span>): <span class="hljs-built_in">Promise</span>&lt;<span class="hljs-built_in">void</span>&gt;
  clear(): <span class="hljs-built_in">Promise</span>&lt;<span class="hljs-built_in">void</span>&gt;
  length(): <span class="hljs-built_in">Promise</span>&lt;<span class="hljs-built_in">number</span>&gt;
  key(keyIndex: <span class="hljs-built_in">number</span>): <span class="hljs-built_in">Promise</span>&lt;<span class="hljs-built_in">string</span>&gt;
  _config?: {
    name: <span class="hljs-built_in">string</span>
  }
}</code></pre>
				<p>You can note 2 differences here -</p>
				<ol>
					<li>All functions are asynchronous with Promises (because WebSQL and IndexedDB are async)</li>
					<li>It works on objects too (not just strings)</li>
				</ol>
				<p>I have made <code>vuex-persist</code> compatible with both types of storages, but this comes at a slight cost.
					When using asynchronous (promise-based) storages, your state will <strong>not</strong> be
					immediately restored into vuex from localForage. It will go into the event loop
				and will finish when the JS thread is empty. This can invoke a delay of few seconds.</p>
				<a href="#how-to-know-when-async-store-has-been-replaced" id="how-to-know-when-async-store-has-been-replaced" style="color: inherit; text-decoration: none;">
					<h3>How to know when async store has been replaced</h3>
				</a>
				<p>As noted above, the store is not immediately restored from async stores like localForage. This can have the unfortunate side effect of overwriting mutations to the store that happen before <code>vuex-persist</code> has a chance to do its thing. In strict mode, you can create a plugin to subscribe to <strong><code>RESTORE_MUTATION</code></strong> so that you tell your app to wait until the state has been restored before committing any further mutations. (<a href="https://github.com/championswimmer/vuex-persist/issues/15">Issue #15 demonstrates how to write such a plugin.</a>) However, since you should turn strict mode off in production, and since <a href="https://github.com/vuejs/vuex/issues/1316"><code>vuex</code> doesn&#39;t currently provide any kind of notification when <code>replaceState()</code> has been called</a>, starting with <code>v2.1.0</code> <code>vuex-persist</code> will add a <code>restored</code> property to the <code>store</code> object to let you know the state has been restored and that it is now safe to commit any mutations that modify the stored state. <code>store.restored</code> will contain the Promise returned by calling the async version of <code>restoreState()</code>.</p>
				<p>Here&#39;s an example of a <code>beforeEach()</code> hook in <code>vuex-router</code> that will cause your app to wait for <code>vuex-persist</code> to restore the state before taking any further actions:</p>
				<pre><code class="language-js"><span class="hljs-comment">// in src/router.js</span>
<span class="hljs-keyword">import</span> Vue <span class="hljs-keyword">from</span> <span class="hljs-string">'vue'</span>
<span class="hljs-keyword">import</span> Router <span class="hljs-keyword">from</span> <span class="hljs-string">'vue-router'</span>
<span class="hljs-keyword">import</span> { store } <span class="hljs-keyword">from</span> <span class="hljs-string">'@/store'</span> <span class="hljs-comment">// ...or wherever your `vuex` store is defined</span>

Vue.use(Router)

<span class="hljs-keyword">const</span> router = <span class="hljs-keyword">new</span> Router({
  <span class="hljs-comment">// define your router as you normally would</span>
})

<span class="hljs-keyword">const</span> waitForStorageToBeReady = <span class="hljs-keyword">async</span> (to, <span class="hljs-keyword">from</span>, next) =&gt; {
  <span class="hljs-keyword">await</span> store.restored
  next()
}
router.beforeEach(waitForStorageToBeReady)

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> router</code></pre>
				<p>Note that on the 2nd and subsequent router requests to your app, the Promise in <code>store.restored</code> should already be in a &quot;resolved&quot; state, so the hook will <em>not</em> force your app to wait for additional calls to <code>restoreState()</code>.</p>
				<a href="#unit-testing" id="unit-testing" style="color: inherit; text-decoration: none;">
					<h2>Unit Testing</h2>
				</a>
				<a href="#jest" id="jest" style="color: inherit; text-decoration: none;">
					<h3>Jest</h3>
				</a>
				<p>When testing with Jest, you might find this error -</p>
				<pre><code>TypeError: Cannot <span class="hljs-keyword">read</span> <span class="hljs-keyword">property</span><span class="hljs-title"> </span>'getItem' of undefined</code></pre><p>This is because there is no localStorage in Jest. You can add the following Jest plugins to solve this
				<a href="https://www.npmjs.com/package/jest-localstorage-mock">https://www.npmjs.com/package/jest-localstorage-mock</a></p>
			</div>
		</div>
		<div class="col-4 col-menu menu-sticky-wrap menu-highlight">
			<nav class="tsd-navigation primary">
				<ul>
					<li class="globals  ">
						<a href="globals.html"><em>Globals</em></a>
					</li>
					<li class=" tsd-kind-external-module">
						<a href="modules/_asyncstorage_.html">&quot;<wbr>Async<wbr>Storage&quot;</a>
					</li>
					<li class=" tsd-kind-external-module">
						<a href="modules/_mockstorage_.html">&quot;<wbr>Mock<wbr>Storage&quot;</a>
					</li>
					<li class=" tsd-kind-external-module">
						<a href="modules/_persistoptions_.html">&quot;<wbr>Persist<wbr>Options&quot;</a>
					</li>
					<li class=" tsd-kind-external-module">
						<a href="modules/_simplepromisequeue_.html">&quot;<wbr>Simple<wbr>Promise<wbr>Queue&quot;</a>
					</li>
					<li class=" tsd-kind-external-module">
						<a href="modules/_index_.html">&quot;index&quot;</a>
					</li>
					<li class=" tsd-kind-external-module">
						<a href="modules/_utils_.html">&quot;utils&quot;</a>
					</li>
				</ul>
			</nav>
			<nav class="tsd-navigation secondary menu-sticky">
				<ul class="before-current">
				</ul>
			</nav>
		</div>
	</div>
</div>
<footer class="with-border-bottom">
	<div class="container">
		<h2>Legend</h2>
		<div class="tsd-legend-group">
			<ul class="tsd-legend">
				<li class="tsd-kind-module"><span class="tsd-kind-icon">Module</span></li>
				<li class="tsd-kind-object-literal"><span class="tsd-kind-icon">Object literal</span></li>
				<li class="tsd-kind-variable"><span class="tsd-kind-icon">Variable</span></li>
				<li class="tsd-kind-function"><span class="tsd-kind-icon">Function</span></li>
				<li class="tsd-kind-function tsd-has-type-parameter"><span class="tsd-kind-icon">Function with type parameter</span></li>
				<li class="tsd-kind-index-signature"><span class="tsd-kind-icon">Index signature</span></li>
				<li class="tsd-kind-type-alias"><span class="tsd-kind-icon">Type alias</span></li>
				<li class="tsd-kind-type-alias tsd-has-type-parameter"><span class="tsd-kind-icon">Type alias with type parameter</span></li>
			</ul>
			<ul class="tsd-legend">
				<li class="tsd-kind-enum"><span class="tsd-kind-icon">Enumeration</span></li>
				<li class="tsd-kind-enum-member"><span class="tsd-kind-icon">Enumeration member</span></li>
				<li class="tsd-kind-property tsd-parent-kind-enum"><span class="tsd-kind-icon">Property</span></li>
				<li class="tsd-kind-method tsd-parent-kind-enum"><span class="tsd-kind-icon">Method</span></li>
			</ul>
			<ul class="tsd-legend">
				<li class="tsd-kind-interface"><span class="tsd-kind-icon">Interface</span></li>
				<li class="tsd-kind-interface tsd-has-type-parameter"><span class="tsd-kind-icon">Interface with type parameter</span></li>
				<li class="tsd-kind-constructor tsd-parent-kind-interface"><span class="tsd-kind-icon">Constructor</span></li>
				<li class="tsd-kind-property tsd-parent-kind-interface"><span class="tsd-kind-icon">Property</span></li>
				<li class="tsd-kind-method tsd-parent-kind-interface"><span class="tsd-kind-icon">Method</span></li>
				<li class="tsd-kind-index-signature tsd-parent-kind-interface"><span class="tsd-kind-icon">Index signature</span></li>
			</ul>
			<ul class="tsd-legend">
				<li class="tsd-kind-class"><span class="tsd-kind-icon">Class</span></li>
				<li class="tsd-kind-class tsd-has-type-parameter"><span class="tsd-kind-icon">Class with type parameter</span></li>
				<li class="tsd-kind-constructor tsd-parent-kind-class"><span class="tsd-kind-icon">Constructor</span></li>
				<li class="tsd-kind-property tsd-parent-kind-class"><span class="tsd-kind-icon">Property</span></li>
				<li class="tsd-kind-method tsd-parent-kind-class"><span class="tsd-kind-icon">Method</span></li>
				<li class="tsd-kind-accessor tsd-parent-kind-class"><span class="tsd-kind-icon">Accessor</span></li>
				<li class="tsd-kind-index-signature tsd-parent-kind-class"><span class="tsd-kind-icon">Index signature</span></li>
			</ul>
			<ul class="tsd-legend">
				<li class="tsd-kind-constructor tsd-parent-kind-class tsd-is-inherited"><span class="tsd-kind-icon">Inherited constructor</span></li>
				<li class="tsd-kind-property tsd-parent-kind-class tsd-is-inherited"><span class="tsd-kind-icon">Inherited property</span></li>
				<li class="tsd-kind-method tsd-parent-kind-class tsd-is-inherited"><span class="tsd-kind-icon">Inherited method</span></li>
				<li class="tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited"><span class="tsd-kind-icon">Inherited accessor</span></li>
			</ul>
			<ul class="tsd-legend">
				<li class="tsd-kind-property tsd-parent-kind-class tsd-is-protected"><span class="tsd-kind-icon">Protected property</span></li>
				<li class="tsd-kind-method tsd-parent-kind-class tsd-is-protected"><span class="tsd-kind-icon">Protected method</span></li>
				<li class="tsd-kind-accessor tsd-parent-kind-class tsd-is-protected"><span class="tsd-kind-icon">Protected accessor</span></li>
			</ul>
			<ul class="tsd-legend">
				<li class="tsd-kind-property tsd-parent-kind-class tsd-is-private"><span class="tsd-kind-icon">Private property</span></li>
				<li class="tsd-kind-method tsd-parent-kind-class tsd-is-private"><span class="tsd-kind-icon">Private method</span></li>
				<li class="tsd-kind-accessor tsd-parent-kind-class tsd-is-private"><span class="tsd-kind-icon">Private accessor</span></li>
			</ul>
			<ul class="tsd-legend">
				<li class="tsd-kind-property tsd-parent-kind-class tsd-is-static"><span class="tsd-kind-icon">Static property</span></li>
				<li class="tsd-kind-call-signature tsd-parent-kind-class tsd-is-static"><span class="tsd-kind-icon">Static method</span></li>
			</ul>
		</div>
	</div>
</footer>
<div class="container tsd-generator">
	<p>Generated using <a href="https://typedoc.org/" target="_blank">TypeDoc</a></p>
</div>
<div class="overlay"></div>
<script src="assets/js/main.js"></script>
<script>if (location.protocol == 'file:') document.write('<script src="assets/js/search.js"><' + '/script>');</script>
</body>
</html>